#include <iostream>
#include <string>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "Logger.hpp"
#include "Common.hpp"

using namespace LogMudule;

int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        LOG(LogLevel::FATAL) << argv[0] << " severip severport";
        Die(USAGE_ERR);
    }

    u_int16_t severport = std::stoi(argv[2]);
    std::string severip = argv[1];

    int sockfd = ::socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0)
    {
        LOG(LogLevel::FATAL) <<"socket error";
        Die(SOCKET_ERR);
    }
    //填充服务器套接字
    struct sockaddr_in sever;
    memset(&sever,0,sizeof(sever));
    sever.sin_family = AF_INET;
    sever.sin_port  = htons(severport);
    sever.sin_addr.s_addr = inet_addr(severip.c_str());

    while(true)
    {
        std::cout << "Please Enter# ";
        std::string message;
        std::getline(std::cin, message);
        // client 不需要bind吗？socket <-> socket
        // client必须也要有自己的ip和端口！但是客户端，不需要自己显示的调用bind！！
        // 而是，客户端首次sendto消息的时候，由OS自动进行bind
        // 1. 如何理解client自动随机bind端口号？ 一个端口号，只能被一个进程bind
        // 2. 如何理解server要显示的bind？服务器的端口号，必须稳定！！必须是众所周知且不能改变轻易改变的!
        int n = ::sendto(sockfd, message.c_str(),message.size(), 0, Conv(&sever), sizeof(sever));
        if(n < 0)
        {
            LOG(LogLevel::FATAL)<<"sendto fail";
            Die(SENDTO_ERR);
        }

        struct sockaddr_in temp;
        socklen_t len = sizeof(temp);
        char bufferout[1024];
        n = ::recvfrom(sockfd, bufferout, sizeof(bufferout)-1, 0, Conv(&temp), &len);
        if(n < 0)
        {
            LOG(LogLevel::FATAL)<<"recvfrom fail";
            Die(RECV_ERR);
        }
        else if(n > 0)
        {
            bufferout[n] = 0;
            std::cout << bufferout << std::endl;
        }
    }

    return 0;

}